package net.wangds.persistence.columnoriented.conv;

import net.wangds.common.base.module.Holder;
import net.wangds.data.Removable;
import net.wangds.data.WithId;
import net.wangds.log.helper.LogHelper;
import net.wangds.persistence.columnoriented.entity.ColumnOrientedEntity;
import net.wangds.persistence.def.entity.DictTableEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * .
 * <p></p>
 *
 * @author 王东石 2020/10/30 21:51.
 */
@Component
public class DefaultToBeanConv<T extends ColumnOrientedEntity, B extends WithId<String> & Removable>
        extends AbstractColumnOrientedConv
        implements ToBeanConv<T, B>  {

    @Override
    public B convert(List<T> source) {
        if(CollectionUtils.isEmpty(source)) {
            return null;
        }

        DictTableEntity dictTbl = fetchDictTable(source);
        Class<B> entityClass = getBeanClassByName(dictTbl.getBeanClass());

        B res = null;

        try {
            //生成返回值对象
            res = entityClass.newInstance();
            final B fb = res;

            //设置返回值的id字段和删除状态字段
            source.stream().findAny().ifPresent(any->{
                fb.setId(any.getRowKey());
                fb.setRemoved(any.getRemoved());
            });

            //循环设置每个字段列
            source.forEach(f->{
                PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(entityClass, f.getField());
                if(pd==null){
                    return;
                }
                Method wm = pd.getWriteMethod();
                try {
                    wm.invoke(fb, fetchFieldVal(f));
                } catch (IllegalAccessException|InvocationTargetException e) {
                    LogHelper.error(e);
                }
            });

        } catch (InstantiationException|IllegalAccessException e) {
            LogHelper.error(e);
        }



        return res;

    }

    private Object fetchFieldVal(T f) {

        switch (f.getDataType()){
            case Text:
                return f.getTextVal();
            case MidText:
                return f.getMidTextVal();
            case BigText:
                return f.getBigTextVal();
            case Int:
                return f.getIntVal();
            case Dec:
                return f.getDecVal();
        }
        return null;
    }

    /**
     * 根据列字段列表，获得表定义.
     * @param source 列字段实体列表.
     * @return 当前对象得表定义.
     */
    private DictTableEntity fetchDictTable(List<T> source) {

        Holder<DictTableEntity> hdl = Holder.empty();

        source.stream().findAny().flatMap(fld -> repoDictTbl.findByFieldClass(fld.getClass().getName()))
                .ifPresent(dictTbl -> hdl.target = dictTbl);

        return hdl.target;

    }


}
